/**
 * 获取小数点后数字长度
 * @author zhongjiewang
 * @param  {Number} num 数字
 * @return {Number}     长度
 */
function decimalLength(num) {
  const str = num.toString();
  const index = str.indexOf('.');
  return index === -1 ? 0 : str.substr(index + 1).length;
}

/**
 * 小数点后补齐0作为整数
 * @author zhongjiewang
 * @param  {Number} num    数字
 * @param  {Number} length 补齐的长度
 * @return {Number}        整数
 */
function suffixInteger(num, length) {
  let str = num.toString();
  const decimalLen = decimalLength(num);
  str += (10 ** (length - decimalLen)).toString().substr(1);
  return Number(str.replace('.', ''));
}

export class Calculate {
  static AND(x: number, y: number) {
    if (x === y) {
      return x;
    }
    // 大于2的31次方，js与无效
    if (x > 2147483648 || y > 2147483648) {
      const result: Array<number> = [];
      // 转换成二进制数组后再每一位进行与
      const maxtmp = x > y ? x.toString(2).split('') : y.toString(2).split('');
      const mintmp = x < y ? x.toString(2).split('') : y.toString(2).split('');
      // 数据序号：0123456789  转数组后，0为数值最高位
      //          1000010000
      //             0000011
      // 只需要对比小的数即可,从最高位开始对比
      for (let i = 0; i < mintmp.length; i++) {
        result[i] = parseInt(maxtmp[maxtmp.length - mintmp.length + i]) & parseInt(mintmp[i]);
      }
      return parseInt(result.join(''), 2);
    } else {
      return x & y;
    }
  }

  static OR(x: number, y: number) {
    // 大于2的31次方，js或无效
    if (x > 2147483648 || y > 2147483648) {
      // 转换成二进制数组后再每一位进行或
      const maxtmp = x > y ? x.toString(2).split('') : y.toString(2).split('');
      const mintmp = x < y ? x.toString(2).split('') : y.toString(2).split('');
      // 只需要对比小的数即可,从最高位开始对比
      for (let i = 0; i < mintmp.length; i++) {
        maxtmp[maxtmp.length - mintmp.length + i] = (
          parseInt(maxtmp[maxtmp.length - mintmp.length + i]) | parseInt(mintmp[i])
        ).toString();
      }
      return parseInt(maxtmp.join(''), 2);
    } else {
      return x | y;
    }
  }

  /**
   * 加法
   * @static
   * @param {number} num1
   * @param {number} num2
   * @returns
   * @memberof Caculate
   */
  static ADD(num1: number, num2: number) {
    const r1 = decimalLength(num1);
    const r2 = decimalLength(num2);

    const max = Math.max(r1, r2);

    const n1 = suffixInteger(num1, max);
    const n2 = suffixInteger(num2, max);

    return Number(((n1 + n2) / 10 ** max).toFixed(max));
  }

  /**
   *  减法
   * @static
   * @param {number} num1
   * @param {number} num2
   * @returns
   * @memberof Caculate
   */
  static SUB(num1: number, num2: number) {
    const r1 = decimalLength(num1);
    const r2 = decimalLength(num2);

    const max = Math.max(r1, r2);

    const n1 = suffixInteger(num1, max);
    const n2 = suffixInteger(num2, max);

    return Number(((n1 - n2) / 10 ** max).toFixed(max));
  }

  /**
   *  乘法
   * @static
   * @param {number} num1
   * @param {number} num2
   * @returns
   * @memberof Caculate
   */
  static MUL(num1: number, num2: number) {
    const r1 = decimalLength(num1);
    const r2 = decimalLength(num2);

    const max = Math.max(r1, r2);

    const n1 = suffixInteger(num1, max);
    const n2 = suffixInteger(num2, max);

    return (n1 * n2) / 10 ** (max * 2);
  }

  /**
   * 除法
   * @static
   * @param {number} num1  被除数
   * @param {number} num2 除数
   * @returns
   * @memberof Caculate
   */
  static DIV(num1: number, num2: number) {
    const r1 = decimalLength(num1);
    const r2 = decimalLength(num2);

    const max = Math.max(r1, r2);

    const n1 = suffixInteger(num1, max);
    const n2 = suffixInteger(num2, max);

    return n1 / n2;
  }
}
